/**
 * Apply the JVM Toolchain conventions
 * See https://docs.gradle.org/current/userguide/toolchains.html
 *
 * One can choose the toolchain to use for compiling and running the TEST sources.
 * These options apply to Java, Kotlin and Groovy test sources when available.
 * {@code "./gradlew check -PtestToolchain=22"} will use a JDK22
 * toolchain for compiling and running the test SourceSet.
 *
 * By default, the main build will fall back to using the a JDK 17
 * toolchain (and 17 language level) for all main sourceSets.
 * See {@link org.springframework.build.JavaConventions}.
 *
 * Gradle will automatically detect JDK distributions in well-known locations.
 * The following command will list the detected JDKs on the host.
 * {@code
 * $ ./gradlew -q javaToolchains
 * }
 *
 * We can also configure ENV variables and let Gradle know about them:
 * {@code
 * $ echo JDK17
 * /opt/openjdk/java17
 * $ echo JDK22
 * /opt/openjdk/java22
 * $ ./gradlew -Porg.gradle.java.installations.fromEnv=JDK17,JDK22 check
 * }
 *
 * @author Brian Clozel
 * @author Sam Brannen
 */

def testToolchainConfigured() {
	return project.hasProperty('testToolchain') && project.testToolchain
}

def testToolchainLanguageVersion() {
	if (testToolchainConfigured()) {
		return JavaLanguageVersion.of(project.testToolchain.toString())
	}
	return JavaLanguageVersion.of(17)
}

plugins.withType(JavaPlugin).configureEach {
	// Configure a specific Java Toolchain for compiling and running tests if the 'testToolchain' property is defined
	if (testToolchainConfigured()) {
		def testLanguageVersion = testToolchainLanguageVersion()
		tasks.withType(JavaCompile).matching { it.name.contains("Test") }.configureEach {
			javaCompiler = javaToolchains.compilerFor {
				languageVersion = testLanguageVersion
			}
		}
		tasks.withType(Test).configureEach{
			javaLauncher = javaToolchains.launcherFor {
				languageVersion = testLanguageVersion
			}
			// Enable Java experimental support in Bytebuddy
			// Remove when JDK 22 is supported by Mockito
			if (testLanguageVersion == JavaLanguageVersion.of(22)) {
				jvmArgs("-Dnet.bytebuddy.experimental=true")
			}
		}
	}
}

// Configure the JMH plugin to use the toolchain for generating and running JMH bytecode
pluginManager.withPlugin("me.champeau.jmh") {
	if (testToolchainConfigured()) {
		tasks.matching { it.name.contains('jmh') && it.hasProperty('javaLauncher') }.configureEach {
			javaLauncher.set(javaToolchains.launcherFor {
				languageVersion.set(testToolchainLanguageVersion())
			})
		}
		tasks.withType(JavaCompile).matching { it.name.contains("Jmh") }.configureEach {
			javaCompiler = javaToolchains.compilerFor {
				languageVersion = testToolchainLanguageVersion()
			}
		}
	}
}

// Store resolved Toolchain JVM information as custom values in the build scan.
rootProject.ext {
	resolvedMainToolchain = false
	resolvedTestToolchain = false
}
gradle.taskGraph.afterTask { Task task, TaskState state ->
	if (!resolvedMainToolchain && task instanceof JavaCompile && task.javaCompiler.isPresent()) {
		def metadata = task.javaCompiler.get().metadata
		task.project.develocity.buildScan.value('Main toolchain', "$metadata.vendor $metadata.languageVersion ($metadata.installationPath)")
		resolvedMainToolchain = true
	}
	if (testToolchainConfigured() && !resolvedTestToolchain && task instanceof Test && task.javaLauncher.isPresent()) {
		def metadata = task.javaLauncher.get().metadata
		task.project.develocity.buildScan.value('Test toolchain', "$metadata.vendor $metadata.languageVersion ($metadata.installationPath)")
		resolvedTestToolchain = true
	}
}
